package v1

import (
	"fmt"
	"strconv"
	"wms/internal/model/request"
	"wms/internal/service"
	"wms/pkg/common"
	"wms/pkg/logger"

	"github.com/gin-gonic/gin"
	"go.uber.org/zap"
)

// WarehouseController 仓库控制器
type WarehouseController struct {
	service *service.WarehouseService
}

// NewWarehouseController 创建仓库控制器
func NewWarehouseController() *WarehouseController {
	return &WarehouseController{
		service: service.NewWarehouseService(),
	}
}

// Create godoc
// @Summary 创建仓库
// @Description 创建新的仓库
// @Tags 仓库管理
// @Accept json
// @Produce json
// @Security Bearer
// @Param request body request.WarehouseCreateRequest true "仓库信息"
// @Success 200 {object} resp.Response "成功"
// @Failure 400 {object} resp.Response "请求错误"
// @Failure 500 {object} resp.Response "内部错误"
// @Router /warehouses [post]
func (c *WarehouseController) Create(ctx *gin.Context) {
	var req request.WarehouseCreateRequest
	if err := ctx.ShouldBindJSON(&req); err != nil {
		logger.Warn("绑定创建仓库请求参数失败", zap.Error(err))
		common.Error(ctx, err)
		return
	}

	// 获取当前用户ID
	userID := common.GetUserID(ctx)

	if err := c.service.CreateWarehouse(&req, userID); err != nil {
		logger.Error("创建仓库失败", zap.Error(err), zap.Any("req", req))
		common.Error(ctx, err)
		return
	}

	common.Success(ctx, nil)
}

// Update godoc
// @Summary 更新仓库
// @Description 更新仓库信息
// @Tags 仓库管理
// @Accept json
// @Produce json
// @Security Bearer
// @Param id path int true "仓库ID"
// @Param request body request.WarehouseUpdateRequest true "仓库信息"
// @Success 200 {object} resp.Response "成功"
// @Failure 400 {object} resp.Response "请求错误"
// @Failure 500 {object} resp.Response "内部错误"
// @Router /warehouses/{id} [put]
func (c *WarehouseController) Update(ctx *gin.Context) {
	id, err := strconv.ParseUint(ctx.Param("id"), 10, 32)
	if err != nil {
		logger.Warn("解析仓库ID失败", zap.Error(err))
		common.Error(ctx, fmt.Errorf("无效的仓库ID"))
		return
	}

	var req request.WarehouseUpdateRequest
	if err := ctx.ShouldBindJSON(&req); err != nil {
		logger.Warn("绑定更新仓库请求参数失败", zap.Error(err))
		common.Error(ctx, err)
		return
	}

	// 获取当前用户ID
	userID := common.GetUserID(ctx)

	req.ID = uint(id)
	if err := c.service.UpdateWarehouse(&req, userID); err != nil {
		logger.Error("更新仓库失败", zap.Error(err), zap.Any("req", req))
		common.Error(ctx, err)
		return
	}

	common.Success(ctx, nil)
}

// Delete godoc
// @Summary 删除仓库
// @Description 删除指定仓库
// @Tags 仓库管理
// @Accept json
// @Produce json
// @Security Bearer
// @Param id path int true "仓库ID"
// @Success 200 {object} resp.Response "成功"
// @Failure 400 {object} resp.Response "请求错误"
// @Failure 500 {object} resp.Response "内部错误"
// @Router /warehouses/{id} [delete]
func (c *WarehouseController) Delete(ctx *gin.Context) {
	id, err := strconv.ParseUint(ctx.Param("id"), 10, 32)
	if err != nil {
		logger.Warn("解析仓库ID失败", zap.Error(err))
		common.Error(ctx, fmt.Errorf("无效的仓库ID"))
		return
	}

	// 获取当前用户ID
	userID := common.GetUserID(ctx)

	if err := c.service.DeleteWarehouse(uint(id), userID); err != nil {
		logger.Error("删除仓库失败", zap.Error(err), zap.Uint("id", uint(id)))
		common.Error(ctx, err)
		return
	}

	common.Success(ctx, nil)
}

// Get godoc
// @Summary 获取仓库详情
// @Description 获取指定仓库的详细信息
// @Tags 仓库管理
// @Accept json
// @Produce json
// @Security Bearer
// @Param id path int true "仓库ID"
// @Success 200 {object} resp.Response{data=model.Warehouse} "成功"
// @Failure 400 {object} resp.Response "请求错误"
// @Failure 500 {object} resp.Response "内部错误"
// @Router /warehouses/{id} [get]
func (c *WarehouseController) Get(ctx *gin.Context) {
	id, err := strconv.ParseUint(ctx.Param("id"), 10, 32)
	if err != nil {
		logger.Warn("解析仓库ID失败", zap.Error(err))
		common.Error(ctx, fmt.Errorf("无效的仓库ID"))
		return
	}

	warehouse, err := c.service.GetWarehouseByID(uint(id))
	if err != nil {
		logger.Error("获取仓库详情失败", zap.Error(err), zap.Uint("id", uint(id)))
		common.Error(ctx, err)
		return
	}

	common.Success(ctx, warehouse)
}

// List godoc
// @Summary 获取仓库列表
// @Description 获取仓库列表，支持分页和搜索
// @Tags 仓库管理
// @Accept json
// @Produce json
// @Security Bearer
// @Param page query int false "页码" default(1)
// @Param page_size query int false "每页数量" default(10)
// @Param keyword query string false "搜索关键词"
// @Success 200 {object} resp.Response{data=[]model.Warehouse} "成功"
// @Failure 400 {object} resp.Response "请求错误"
// @Failure 500 {object} resp.Response "内部错误"
// @Router /warehouses [get]
func (c *WarehouseController) List(ctx *gin.Context) {
	var req request.WarehouseListRequest
	if err := ctx.ShouldBindQuery(&req); err != nil {
		logger.Warn("绑定仓库列表请求参数失败", zap.Error(err))
		common.Error(ctx, err)
		return
	}

	list, total, err := c.service.ListWarehouses(&req)
	if err != nil {
		logger.Error("获取仓库列表失败", zap.Error(err), zap.Any("req", req))
		common.Error(ctx, err)
		return
	}

	common.Success(ctx, gin.H{
		"list":  list,
		"total": total,
		"page":  req.Page,
		"size":  req.PageSize,
	})
}

// CreateLocation godoc
// @Summary 创建货位
// @Description 创建新的货位
// @Tags 货位管理
// @Accept json
// @Produce json
// @Security Bearer
// @Param request body request.LocationCreateRequest true "货位信息"
// @Success 200 {object} resp.Response "成功"
// @Failure 400 {object} resp.Response "请求错误"
// @Failure 500 {object} resp.Response "内部错误"
// @Router /warehouses/locations [post]
func (c *WarehouseController) CreateLocation(ctx *gin.Context) {
	var req request.LocationCreateRequest
	if err := ctx.ShouldBindJSON(&req); err != nil {
		logger.Warn("绑定创建货位请求参数失败", zap.Error(err))
		common.Error(ctx, err)
		return
	}

	// 获取当前用户ID
	userID := common.GetUserID(ctx)

	if err := c.service.CreateLocation(&req, userID); err != nil {
		logger.Error("创建货位失败", zap.Error(err), zap.Any("req", req))
		common.Error(ctx, err)
		return
	}

	common.Success(ctx, nil)
}

// UpdateLocation godoc
// @Summary 更新货位
// @Description 更新货位信息
// @Tags 货位管理
// @Accept json
// @Produce json
// @Security Bearer
// @Param id path int true "货位ID"
// @Param request body request.LocationUpdateRequest true "货位信息"
// @Success 200 {object} resp.Response "成功"
// @Failure 400 {object} resp.Response "请求错误"
// @Failure 500 {object} resp.Response "内部错误"
// @Router /warehouses/locations/{id} [put]
func (c *WarehouseController) UpdateLocation(ctx *gin.Context) {
	id, err := strconv.ParseUint(ctx.Param("id"), 10, 32)
	if err != nil {
		logger.Warn("解析货位ID失败", zap.Error(err))
		common.Error(ctx, fmt.Errorf("无效的货位ID"))
		return
	}

	var req request.LocationUpdateRequest
	if err := ctx.ShouldBindJSON(&req); err != nil {
		logger.Warn("绑定更新货位请求参数失败", zap.Error(err))
		common.Error(ctx, err)
		return
	}

	// 获取当前用户ID
	userID := common.GetUserID(ctx)

	req.ID = uint(id)
	if err := c.service.UpdateLocation(&req, userID); err != nil {
		logger.Error("更新货位失败", zap.Error(err), zap.Any("req", req))
		common.Error(ctx, err)
		return
	}

	common.Success(ctx, nil)
}

// DeleteLocation godoc
// @Summary 删除货位
// @Description 删除指定货位
// @Tags 货位管理
// @Accept json
// @Produce json
// @Security Bearer
// @Param id path int true "货位ID"
// @Success 200 {object} resp.Response "成功"
// @Failure 400 {object} resp.Response "请求错误"
// @Failure 500 {object} resp.Response "内部错误"
// @Router /warehouses/locations/{id} [delete]
func (c *WarehouseController) DeleteLocation(ctx *gin.Context) {
	id, err := strconv.ParseUint(ctx.Param("id"), 10, 32)
	if err != nil {
		logger.Warn("解析货位ID失败", zap.Error(err))
		common.Error(ctx, fmt.Errorf("无效的货位ID"))
		return
	}

	// 获取当前用户ID
	userID := common.GetUserID(ctx)

	if err := c.service.DeleteLocation(uint(id), userID); err != nil {
		logger.Error("删除货位失败", zap.Error(err), zap.Uint("id", uint(id)))
		common.Error(ctx, err)
		return
	}

	common.Success(ctx, nil)
}

// GetLocation godoc
// @Summary 获取货位详情
// @Description 获取指定货位的详细信息
// @Tags 货位管理
// @Accept json
// @Produce json
// @Security Bearer
// @Param id path int true "货位ID"
// @Success 200 {object} resp.Response{data=model.Location} "成功"
// @Failure 400 {object} resp.Response "请求错误"
// @Failure 500 {object} resp.Response "内部错误"
// @Router /warehouses/locations/{id} [get]
func (c *WarehouseController) GetLocation(ctx *gin.Context) {
	id, err := strconv.ParseUint(ctx.Param("id"), 10, 32)
	if err != nil {
		logger.Warn("解析货位ID失败", zap.Error(err))
		common.Error(ctx, fmt.Errorf("无效的货位ID"))
		return
	}

	location, err := c.service.GetLocationByID(uint(id))
	if err != nil {
		logger.Error("获取货位详情失败", zap.Error(err), zap.Uint("id", uint(id)))
		common.Error(ctx, err)
		return
	}

	common.Success(ctx, location)
}

// ListLocations godoc
// @Summary 获取货位列表
// @Description 获取货位列表，支持分页和搜索
// @Tags 货位管理
// @Accept json
// @Produce json
// @Security Bearer
// @Param page query int false "页码" default(1)
// @Param page_size query int false "每页数量" default(10)
// @Param warehouse_id query int false "仓库ID"
// @Param keyword query string false "搜索关键词"
// @Success 200 {object} resp.Response{data=[]model.Location} "成功"
// @Failure 400 {object} resp.Response "请求错误"
// @Failure 500 {object} resp.Response "内部错误"
// @Router /warehouses/locations [get]
func (c *WarehouseController) ListLocations(ctx *gin.Context) {
	var req request.LocationListRequest
	if err := ctx.ShouldBindQuery(&req); err != nil {
		logger.Warn("绑定货位列表请求参数失败", zap.Error(err))
		common.Error(ctx, err)
		return
	}

	list, total, err := c.service.ListLocations(&req)
	if err != nil {
		logger.Error("获取货位列表失败", zap.Error(err), zap.Any("req", req))
		common.Error(ctx, err)
		return
	}

	common.Success(ctx, gin.H{
		"list":  list,
		"total": total,
		"page":  req.Page,
		"size":  req.PageSize,
	})
}

// ListAvailableLocations godoc
// @Summary 获取可用货位列表 (状态为启用)
// @Description 获取指定仓库下状态为启用的货位列表
// @Tags 货位管理
// @Accept json
// @Produce json
// @Security Bearer
// @Param warehouse_id query int true "仓库ID"
// @Param keyword query string false "搜索关键词"
// @Success 200 {object} resp.Response{data=[]model.Location} "成功"
// @Failure 400 {object} resp.Response "请求错误"
// @Failure 500 {object} resp.Response "内部错误"
// @Router /warehouses/locations/available [get]
func (c *WarehouseController) ListAvailableLocations(ctx *gin.Context) {
	var req request.LocationListRequest
	if err := ctx.ShouldBindQuery(&req); err != nil {
		logger.Warn("绑定可用货位列表请求参数失败", zap.Error(err))
		common.Error(ctx, err)
		return
	}

	// 强制设置状态为启用 (Status=1)
	enabledStatus := 1
	req.Status = &enabledStatus

	// 通常可用列表不需要分页，但保留分页逻辑以防万一
	if req.Page <= 0 {
		req.Page = 1
	}
	if req.PageSize <= 0 {
		req.PageSize = 999 // 获取足够多的数据，模拟不分页
	}

	list, _, err := c.service.ListLocations(&req) // 调用现有的 ListLocations 服务
	if err != nil {
		logger.Error("获取可用货位列表失败", zap.Error(err), zap.Any("req", req))
		common.Error(ctx, err)
		return
	}

	common.Success(ctx, list)
}
